package com.xuecheng.content.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xuecheng.api.content.model.dto.CourseBaseDTO;
import com.xuecheng.api.content.model.qo.QueryCourseBaseModel;
import com.xuecheng.common.domain.code.CommonErrorCode;
import com.xuecheng.common.domain.page.PageRequestParams;
import com.xuecheng.common.domain.page.PageVO;
import com.xuecheng.common.enums.common.CommonEnum;
import com.xuecheng.common.enums.content.CourseAuditEnum;
import com.xuecheng.common.enums.content.CourseChargeEnum;
import com.xuecheng.common.util.StringUtil;
import com.xuecheng.content.convert.CourseBaseConvert;
import com.xuecheng.content.entity.CourseBase;
import com.xuecheng.content.entity.CourseMarket;
import com.xuecheng.content.mapper.CourseBaseMapper;
import com.xuecheng.content.service.CourseBaseService;
import com.xuecheng.content.service.CourseMarketService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;

/**
 * <p>
 * 课程基本信息 服务实现类
 * </p>
 *
 * @author itcast
 */
@Slf4j
@Service
public class CourseBaseServiceImpl extends ServiceImpl<CourseBaseMapper, CourseBase> implements CourseBaseService {

 @Autowired
    private CourseMarketService courseMarketService;

    /*
     * 步骤分析：
     *  1.是否需要开启事务
     *  2.判断关键数据
     *       分页数据
     *       查询条件
     *  3.构建mp分页对象
     *  4.构建查询条件对象LambdaQueryWrapper
     *  5.查询数据
     *  6.获得数据并封装返回结果
     *       封装PageVo数据
     * */
    @Override
    public PageVO queryCourseBaseList(PageRequestParams params, QueryCourseBaseModel model, Long companyId) {

          // 步骤分析：
         //  1.是否需要开启事务 ：查询不需要开启事务
         //  2.判断关键数据
         //       分页数据
        Long pageNo = params.getPageNo();
        Integer pageSize = params.getPageSize();
        if(ObjectUtils.isEmpty(pageNo) || pageNo<0){
            params.setPageNo(PageRequestParams.DEFAULT_PAGE_NUM);
        }
        if(ObjectUtils.isEmpty(pageSize)||pageSize<0){
            params.setPageSize(PageRequestParams.DEFAULT_PAGE_SIZE);
        }
        //       查询条件
        //LambdaQueryWrapper<CourseBase> queryWrapper = new LambdaQueryWrapper<>();
        LambdaQueryWrapper<CourseBase> queryWrapper = Wrappers.lambdaQuery();
       // queryWrapper.like(StringUtil.isNotBlank(model.getCourseName()),CourseBase::getName,model.getCourseName());
        //queryWrapper.eq(StringUtil.isNotBlank(model.getAuditStatus()),CourseBase::getAuditStatus,model.getAuditStatus());

        queryWrapper.like(StringUtils.isEmpty(model.getCourseName()),CourseBase::getName,model.getCourseName());
        queryWrapper.eq(StringUtils.isEmpty(model.getAuditStatus()),CourseBase::getAuditStatus,model.getAuditStatus());
        queryWrapper.eq(CourseBase::getCompanyId,companyId);
        queryWrapper.eq(CourseBase::getStatus, CommonEnum.USING_FLAG.getCode());

        //
         // 3.构建mp分页对象
        Page<CourseBase> page = new Page<>(params.getPageNo(),params.getPageSize());

        // 4.构建查询条件对象LambdaQueryWrapper
        Page<CourseBase> pageResult = this.page(page, queryWrapper);
        // 获得当前页的集合数据
        List<CourseBase> records = pageResult.getRecords();
        // 查询数据的总记录数
        long total = pageResult.getTotal();
       // 将po数据转为dto数据
        List<CourseBaseDTO> dtos = Collections.EMPTY_LIST;
        if(!(CollectionUtils.isEmpty(records))){
            dtos= CourseBaseConvert.INSTANCE.entitys2dtos(records);
        }
        // 6.获得数据并封装返回结果
         //      封装PageVo数据
        PageVO pageVO = new PageVO(dtos,total,params.getPageNo(),params.getPageSize());
        return pageVO;

    }
    /*
     * 业务分析：
     *   1.是否开启事务
     *     新增操作需要开启事务
     *       如果新增操作只会操作一张表而且只会操作一次，那么可以忽略事务
     *   2.判断关键数据
     *       课程基础信息
     *           关键数据：表中内容的必要数据，无此数据代表数据不完整
     *           关键数据的来源：
     *               1.数据库的约束
     *                   不能为空的字段
     *               2.前端页面中必要数据
     *                   用小红点来显示
     *               3.接口文档：Yapi
     *                   会体现出必要的数据
     *   3.将dto转为po数据，并且赋值审核状态的默认值
     *       保存：未提交
     *   4.保存数据
     *       4.1 保存课程基础信息
     *           判断保存的结果
     *       4.2 保存课程营销信息
     *           判断保存的结果
     *   5.将数据库的最新数据转为dto并返回
     * */
    @Override
    @Transactional
    public CourseBaseDTO createCourseBase(CourseBaseDTO dto) {

//        2.判断关键数据
//            课程基础信息
//        关键数据：表中内容的必要数据，无此数据代表数据不完整
//                关键数据的来源：
//                    1.数据库的约束
//                        不能为空的字段
//                    2.前端页面中必要数据
//                        用小红点来显示
//                    3.接口文档：Yapi
//                        会体现出必要的数据
        // companyId  name  mt st  grade teachmode  users  pic（后期来判断）
        verifyCourseBaseMsg(dto);
//
//        3.将dto转为po数据，并且赋值审核状态的默认值
        CourseBase courseBase = CourseBaseConvert.INSTANCE.dto2entity(dto);
//            保存：未提交
        courseBase.setAuditStatus(CourseAuditEnum.AUDIT_UNPAST_STATUS.getCode());

//        4.保存数据
//            4.1 保存课程基础信息
//                判断保存的结果
        //注意：mp对数据保存成功后会主键自增回填
        boolean baseResult = this.save(courseBase);
        if(!baseResult){
            throw new RuntimeException("保存课程基础信息失败");
        }
//            4.2 保存课程营销信息
//                判断保存的结果
        CourseMarket courseMarket = new CourseMarket();
        courseMarket.setCourseId(courseBase.getId());
        courseMarket.setCharge(dto.getCharge());


        // 判断课程是否收费：
        //     1.如果是免费，无需给price赋值
        if(CourseChargeEnum.CHARGE_YES.getCode().equals(dto.getCharge())){
            //     2.如果是收费，price必须有值
            if(ObjectUtils.isEmpty(dto.getPrice())){
                throw new RuntimeException("收费课程的价格不能为空");
            }
            courseMarket.setPrice(dto.getPrice().floatValue());
        }
        boolean marketResult= courseMarketService.save(courseMarket);
        if(!marketResult){
            throw new RuntimeException("课程营销信息保存失败");
        }

//        5.将数据库的最新数据转为dto并返回
        CourseBaseDTO resultDTO = CourseBaseConvert.INSTANCE.entity2dto(courseBase);
        resultDTO.setCharge(dto.getCharge());
        resultDTO.setPrice(dto.getPrice());
        return resultDTO;
    }

    @Override
    public CourseBaseDTO getByCourseId(Long courseId, Long companyId) {
        //1.判断关键数据
        //     courseId、companyId
        if(ObjectUtils.isEmpty(courseId) ||ObjectUtils.isEmpty(companyId)){
            throw new RuntimeException(CommonErrorCode.E_100101.getDesc());

        }

        // 2.判断业务数据
        //     课程基础信息
        //         课程是否是同一家教学机构
        //         判断课程是否已删除


        // 2.1 根据id查询后和机构的id进行比较（比较麻烦）
        // CourseBase courseBase = this.getById(courseId);
        //
        // if (!(ObjectUtils.nullSafeEquals(companyId,courseBase.getCompanyId()))) {
        //     throw new RuntimeException(CommonErrorCode.E_403000.getDesc());
        // }

        // 2.1 课程是否是同一家教学机构
        // 2.2 判断课程是否已删除
        // 2.1 课程是否是同一家教学机构

        CourseBase courseBase = getCourseBaseAndLogicVerify(courseId, companyId);

        // 3.将数据转为dto并返回
        //  获得课程的营销数据并返回
        CourseBaseDTO dto = CourseBaseConvert.INSTANCE.entity2dto(courseBase);
        LambdaQueryWrapper<CourseMarket> marketQueryWrapper = new LambdaQueryWrapper<>();
        marketQueryWrapper.eq(CourseMarket::getCourseId,courseId);

        CourseMarket market = courseMarketService.getOne(marketQueryWrapper);

        dto.setPrice(new BigDecimal(market.getPrice().toString()));
        dto.setCharge(market.getCharge());
        return dto;

    }

    @Override
    @Transactional
    public CourseBaseDTO modifyCourseBase(CourseBaseDTO dto) {
        //1.判断关键数据
        //    参考添加的判断
        verifyCourseBaseMsg(dto);
        if(ObjectUtils.isEmpty(dto.getCourseBaseId())){
            throw new RuntimeException("修改课程id不能为空");
        }

        // 2.判断业务数据
        //     课程基础信息
        //         判断是否是同一家教学机构
        //         判断课程是否被删除
        //         判断课程的审核状态
        //             只有 未提交、审核未通过 才可以修改数据

        // 修改的数据必须要有Id值
        CourseBase courseBase = getCourseBaseAndLogicVerify(dto.getCourseBaseId(), dto.getCompanyId());
        String auditStatus = courseBase.getAuditStatus();
        if(CourseAuditEnum.AUDIT_PASTED_STATUS.getCode().equals(auditStatus)||
         CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode().equals(auditStatus)||
        CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode().equals(auditStatus)){
            throw new RuntimeException("课程审核状态异常");
        }
        // 3.转换dto数据为po数据
        CourseBase po = CourseBaseConvert.INSTANCE.dto2entity(dto);

        // 4.修改数据
        //     课程基础信息

        // 如果修改的实体数据比较多，updateById（要修改的实体类对象）
        boolean courseResult = this.updateById(po);
        if(!courseResult){
            throw new RuntimeException("修改课程基础信息失败");
        }
        //     课程营销信息
        // 如果修改的实体数据比较少，LambdaUpdateWrapper
        // update course_market set charge = ? ,  price = ? where courseid =?
        LambdaUpdateWrapper<CourseMarket> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(CourseMarket::getCharge,dto.getCharge());
        float price=0L;
        if(CourseChargeEnum.CHARGE_YES.getCode().equals(dto.getCharge())){
            price=dto.getPrice().floatValue();
        }
        updateWrapper.set(CourseMarket::getPrice,price)
                .eq(CourseMarket::getCourseId,dto.getCourseBaseId());
        boolean marketResult = courseMarketService.update(updateWrapper);
        if(!marketResult){
            throw new RuntimeException("修改课程营销信息失败");
        }

        // 5.将最新数据返回给dto
        CourseBase resultPO = this.getById(dto.getCourseBaseId());
        CourseBaseDTO resultDTO = CourseBaseConvert.INSTANCE.entity2dto(resultPO);
        resultDTO.setCharge(dto.getCharge());
        resultDTO.setPrice(dto.getPrice());

        return resultDTO;
    }

    @Override
    @Transactional
    public void removeCourseBase(Long courseId, Long companyId) {
        //1.判断关键数据
        //     courseId、companyId
        if(ObjectUtils.isEmpty(courseId) ||ObjectUtils.isEmpty(companyId)){
            throw new RuntimeException(CommonErrorCode.E_100101.getDesc());

        }
       // CourseBase courseBase = this.getById(courseId);
        // 2.1 课程是否是同一家教学机构
        // 2.2 判断课程是否已删除
        // 2.1 课程是否是同一家教学机构

        CourseBase courseBase = getCourseBaseAndLogicVerify(courseId, companyId);

        //审核状态
        String auditStatus = courseBase.getAuditStatus();
        if(CourseAuditEnum.AUDIT_PASTED_STATUS.getCode().equals(auditStatus)||
                CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode().equals(auditStatus)||
                CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode().equals(auditStatus)){
            throw new RuntimeException("课程审核状态异常");
        }

        // 4.修改数据
        //     课程基础信息

        // 如果修改的实体数据比较多，updateById（要修改的实体类对象）
        LambdaUpdateWrapper<CourseBase> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(CourseBase::getStatus,CommonEnum.DELETE_FLAG.getCodeInt())
                .eq(CourseBase::getId, courseId);

        boolean deleteResult = this.update(updateWrapper);
        if(ObjectUtils.isEmpty(deleteResult)){
            throw new RuntimeException("未成功删除数据");

        }

    }




    private CourseBase getCourseBaseAndLogicVerify(Long courseId, Long companyId) {
        // 2.1 课程是否是同一家教学机构
        LambdaQueryWrapper<CourseBase> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CourseBase::getId, courseId)
                     .eq(CourseBase::getCompanyId, companyId);
        CourseBase courseBase = this.getOne(queryWrapper);
        if(ObjectUtils.isEmpty(courseBase)){
            throw new RuntimeException("课程基础信息不存在");
        }
        // 2.2 判断课程是否已删除
        Integer status = courseBase.getStatus();
        if(CommonEnum.DELETE_FLAG.getCodeInt().equals(status)){
            throw new RuntimeException("课程基础信息已删除");
        }
        return courseBase;
    }


    private void verifyCourseBaseMsg(CourseBaseDTO dto) {
        if(ObjectUtils.isEmpty(dto.getCompanyId())){
            throw  new RuntimeException("公司id不能为空");

        }
        if(StringUtil.isBlank(dto.getName())){
         throw new RuntimeException("课程名称不能为空");
        }
        if(StringUtil.isBlank(dto.getMt())){
            throw new RuntimeException("课程大分类不能为空");
        }
        if(StringUtil.isBlank(dto.getSt())){
            throw new RuntimeException("课程小分类不能为空");
        }
        if(StringUtil.isBlank(dto.getGrade())){
            throw new RuntimeException("课程等级不能为空");
        }
        if(StringUtil.isBlank(dto.getTeachmode())){
            throw new RuntimeException("课程教学模式不能为空");
        }
        if(StringUtil.isBlank(dto.getUsers())){
            throw new RuntimeException("使用人群不能为空");
        }
        if (StringUtil.isBlank(dto.getCharge())) {
            throw new RuntimeException("课程收费不能为空");
        }
    }
}
